package manage

import (
	"bytes"
	"context"
	"encoding/base64"
	"encoding/json"
	"strconv"
	"strings"
	"time"

	"lingc/config"
	"lingc/services"
	"lingc/utils" // 导入 common 包
	"lingc/version"

	"github.com/dchest/captcha"
	"github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
)

// CreateMenu 创建菜单
func CreateMenu(c *gin.Context) {
	version.CreateMenu(c)
	utils.SendJSONResponse(c, 200, gin.H{
		"code": 0,
		"msg":  "菜单创建成功",
	})
}

// GenerateCaptcha 生成验证码
func GenerateCaptcha(c *gin.Context) {
	// 生成一个新的验证码 ID
	captchaID := captcha.NewLen(4)

	// 将生成的验证码图片写入缓冲区
	var buf bytes.Buffer
	err := captcha.WriteImage(&buf, captchaID, 150, 70)
	if err != nil {
		utils.SendJSONResponse(c, utils.BadRequestCode, gin.H{"msg": "Failed to generate captcha image"}) // 替换为 common 包中的函数
		return
	}

	// 将缓冲区中的图片数据编码为Base64
	captchaImageBase64 := base64.StdEncoding.EncodeToString(buf.Bytes())

	// log.Println("Generated captcha ID:", captchaID)
	// log.Println("Generated captcha base64:", captchaImageBase64)
	// utils.SendJSONResponse(c, utils.SuccessCode, gin.H{"msg": "Login successful", "token": captchaImageBase64})
	// 返回 captchaID 和 base64 编码的图片数据给前端
	utils.SendJSONResponse(c, utils.SuccessCode, gin.H{"captcha_id": captchaID, "captcha_image": "data:image/png;base64," + captchaImageBase64}) // 替换为 common 包中的函数
}

// Login 用户登录
func AuthLogin(c *gin.Context) {
	// 前端需要先调用 GenerateCaptcha 接口获取 CaptchaID
	var loginData struct {
		Username  string `json:"username" binding:"required"`
		Password  string `json:"password" binding:"required"`
		Captcha   string `json:"captcha" binding:"required"`
		CaptchaID string `json:"captcha_id" binding:"required"`
	}
	// 获取客户端IP
	var ip = utils.GetClientIP(c)
	if err := c.ShouldBindJSON(&loginData); err != nil {
		utils.SendJSONResponse(c, utils.ErrorCode, gin.H{"msg": err.Error()})
		return
	}
	// 验证验证码
	// if !captcha.VerifyString(loginData.CaptchaID, loginData.Captcha) {
	// 	utils.SendJSONResponse(c, utils.ErrorCode, gin.H{"msg": "Invalid captcha"})
	// 	return
	// }

	user, err := services.NewAuthUserService(utils.MysqlClient).Login(loginData.Username, loginData.Password, ip)
	if err != nil {
		utils.SendJSONResponse(c, utils.ErrorCode, gin.H{"msg": err.Error()})
		return
	}
	// log.Println("user:", user)

	// 创建token
	expirationTime := time.Now().Add(config.AdminTokenTime * time.Minute)
	/**
	ID       uint   `json:"id"`
	Username string `json:"username"`
	Avatar   string `json:"avatar"`
	Realname string `json:"realname"`
	*/
	claims := utils.Claims{
		ID:       user.ID,
		Username: loginData.Username,
		Avatar:   user.Avatar,
		Nickame:  user.Realname,
		Type:     "admin",
		StandardClaims: jwt.StandardClaims{
			ExpiresAt: expirationTime.Unix(),
		},
	}
	tokenString, err := utils.GenerateToken(claims, config.AdminTokenTime)
	if err != nil {
		utils.SendJSONResponse(c, utils.ErrorCode, gin.H{"msg": "Failed to generate token"})
		return
	}
	// 将token存储到Redis中
	utils.SetRedis(utils.GenerateMD5("token_"+loginData.Username), tokenString, config.AdminTokenTime)
	RefreshexpirationTime := time.Now().Add(config.RefreshTokenTime * time.Minute)
	RefreshtokenString, err := utils.GenerateToken(claims, config.RefreshTokenTime)
	if err != nil {
		utils.SendJSONResponse(c, utils.ErrorCode, gin.H{"msg": "Failed to generate RefreshToken"})
		return
	}
	utils.SetRedis(utils.GenerateMD5("RefreshToken_"+loginData.Username), RefreshtokenString, config.RefreshTokenTime)
	// 设置刷新token过期时间
	expires := RefreshexpirationTime.Unix()
	// ... existing code for user authentication ...
	utils.SendJSONResponse(c, utils.SuccessCode, gin.H{"accessToken": tokenString, "expires": expires, "refreshToken": RefreshtokenString})
}

// 刷新Token
func AuthRefreshtoken(c *gin.Context) {
	// 刷新token
	var RefreshData struct {
		RefreshToken string `json:"refreshToken" binding:"required"`
	}
	if err := c.ShouldBindJSON(&RefreshData); err != nil {
		utils.SendJSONResponse(c, utils.ErrorCode, gin.H{"msg": err.Error()})
		return
	}
	user_token := utils.ValidateToken(RefreshData.RefreshToken)
	// log.Printf("刷新token:", user_token)
	// 验证token
	if user_token == nil {
		utils.SendJSONResponse(c, utils.ErrorToken, gin.H{"msg": "无效的token"})
		c.Abort()
		return
	}

	//获取缓存token
	redis_token := utils.GetRedis(utils.GenerateMD5("RefreshToken_" + user_token.Username))
	if redis_token == "" {
		utils.SendJSONResponse(c, utils.ErrorToken, gin.H{"msg": "无效的token", "code": 1})
		c.Abort()
		return
	}
	if RefreshData.RefreshToken != redis_token {
		utils.SendJSONResponse(c, utils.ErrorToken, gin.H{"msg": "无效的token", "code": 2})
		c.Abort()
		return
	}
	user_info, err := services.NewAuthUserService(utils.MysqlClient).GetAuthUserById(user_token.ID)
	if err != nil {
		utils.SendJSONResponse(c, utils.ErrorCode, gin.H{"msg": err.Error()})
		return
	}
	// 创建token
	expirationTime := time.Now().Add(config.AdminTokenTime * time.Minute)
	/**
	ID       uint   `json:"id"`
	Username string `json:"username"`
	Avatar   string `json:"avatar"`
	Realname string `json:"realname"`
	*/
	claims := utils.Claims{
		ID:       user_info.ID,
		Username: user_info.Username,
		Avatar:   user_info.Avatar,
		Nickame:  user_info.Realname,
		Type:     "admin",
		StandardClaims: jwt.StandardClaims{
			ExpiresAt: expirationTime.Unix(),
		},
	}
	tokenString, err := utils.GenerateToken(claims, config.AdminTokenTime)
	if err != nil {
		utils.SendJSONResponse(c, utils.ErrorCode, gin.H{"msg": "Failed to generate token"})
		return
	}
	// 将token存储到Redis中
	utils.SetRedis(utils.GenerateMD5("token_"+user_info.Username), tokenString, config.AdminTokenTime)
	RefreshexpirationTime := time.Now().Add(config.RefreshTokenTime * time.Minute)
	RefreshtokenString, err := utils.GenerateToken(claims, config.RefreshTokenTime)
	if err != nil {
		utils.SendJSONResponse(c, utils.ErrorCode, gin.H{"msg": "Failed to generate RefreshToken"})
		return
	}
	utils.SetRedis(utils.GenerateMD5("RefreshToken_"+user_info.Username), RefreshtokenString, config.RefreshTokenTime)
	// 设置刷新token过期时间
	expires := RefreshexpirationTime.Unix()
	// ... existing code for user authentication ...
	utils.SendJSONResponse(c, utils.SuccessCode, gin.H{"accessToken": tokenString, "expires": expires, "refreshToken": RefreshtokenString})
}

// Logout 用户登出
func AuthLogout(c *gin.Context) {
	userInterface, exists := c.Get("user")
	if !exists {
		utils.SendJSONResponse(c, utils.ErrorToken, gin.H{"msg": "用户未找到"})
		return
	}
	user, ok := userInterface.(*utils.Claims) // 假设 utils.User 是 user 的类型
	if !ok {
		utils.SendJSONResponse(c, utils.ErrorToken, gin.H{"msg": "用户类型失败"})
		return
	}

	key := utils.GenerateMD5("token_" + user.Username)
	utils.RedisClient.Del(context.Background(), key)
	refreshKey := utils.GenerateMD5("RefreshToken_" + user.Username)
	utils.RedisClient.Del(context.Background(), refreshKey)
	utils.SendJSONResponse(c, utils.SuccessCode, gin.H{"msg": "Logout successful"}) // 替换为 common 包中的函数
}

func GetUsersInfo(c *gin.Context) {
	// 获取 user 数据
	userInterface, exists := c.Get("user")
	if !exists {
		utils.SendJSONResponse(c, utils.ErrorToken, gin.H{"msg": "用户未找到"})
		return
	}
	user, ok := userInterface.(*utils.Claims) // 假设 utils.User 是 user 的类型
	if !ok {
		utils.SendJSONResponse(c, utils.ErrorToken, gin.H{"msg": "用户类型失败"})
		return
	}
	user_info, err := services.NewAuthUserService(utils.MysqlClient).GetAuthUserById(user.ID)
	if err != nil {
		utils.SendJSONResponse(c, utils.ErrorCode, gin.H{"msg": err.Error()})
		return
	}
	user_menus, err := services.NewAuthUserService(utils.MysqlClient).GetMenusRouteList(c)

	if err != nil {
		utils.SendJSONResponse(c, utils.ErrorCode, gin.H{"msg": err.Error()})
		return
	}
	var ruleIDs []uint
	roles := "manage"
	if user_info.Username == "admin" {
		roles = "admin"
		for _, v := range user_menus {
			ruleIDs = append(ruleIDs, v.ID)
		}
	} else {
		ruleStr := user_info.AuthGroup.Rules
		//1,2,3,4
		ruleStrs := strings.Split(ruleStr, ",")
		for _, ruleS := range ruleStrs {
			if ruleS == "" {
				continue
			}
			ruleID, err := strconv.Atoi(ruleS)
			if err != nil {
				utils.SendJSONResponse(c, utils.ErrorCode, gin.H{"msg": err.Error()})
				return
			}
			ruleIDs = append(ruleIDs, uint(ruleID))
		}
	}
	ruleIDsJson, err := json.Marshal(ruleIDs)
	if err != nil {
		utils.SendJSONResponse(c, utils.ErrorCode, gin.H{"msg": err.Error()})
		return
	}

	utils.SetRedis("auth_rule_ids_"+strconv.Itoa(int(user.ID)), ruleIDsJson, 24*60)
	// 获取用户权限
	perms := utils.GetMenusUserRoute(ruleIDs, user_menus)
	menus := utils.GetMenusUser(ruleIDs, user_menus)
	user_data := gin.H{
		"user_id":  user_info.ID,
		"username": user_info.Username,
		"realname": user_info.Realname,
		"avatar":   user_info.Avatar,
		"roles":    roles,
		"perms":    perms,
		"menus":    menus,
	}
	// 替换为 common 包中的函数，并返回 user 数据
	utils.SendJSONResponse(c, utils.SuccessCode, user_data)
}
